package com.zzx.business.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzx.business.domain.TbNodes;
import com.zzx.business.mapper.TbFilesMapper;
import com.zzx.business.mapper.TbFlowMapper;
import com.zzx.business.mapper.TbNodesMapper;
import com.zzx.business.service.ITbNodesService;
import com.zzx.business.vo.TbFlowVo;
import com.zzx.business.vo.TbNodesVo;
import com.zzx.common.core.page.TableDataInfo;
import com.zzx.common.utils.DateUtils;
import com.zzx.common.utils.PageUtils;
import com.zzx.business.domain.TbProjects;
import com.zzx.business.vo.TbProjectsVo;
import com.zzx.business.mapper.TbProjectsMapper;
import com.zzx.business.service.ITbProjectsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 项目信息Service业务层处理
 *
 * @author Zzx
 * @date 2025-05-23
 */
@Service
public class TbProjectsServiceImpl extends ServiceImpl<TbProjectsMapper, TbProjects> implements ITbProjectsService {
    @Autowired
    private TbFlowMapper tbFlowMapper;
    @Autowired
    private ITbNodesService tbNodesService;
    @Override
    public TableDataInfo<TbProjectsVo> queryList(TbProjectsVo entity) {
        return PageUtils.buildDataInfo(this.baseMapper.queryList(PageUtils.buildPage(), entity));
    }
    @Override
    public List<TbProjectsVo> queryAll(TbProjectsVo entity) {
        return this.baseMapper.queryList(entity);
    }
    @Override
    public TbProjectsVo queryById(Long id) {
        return this.baseMapper.queryById(id);
    }
    @Transactional
    @Override
    public boolean saveProject(TbProjectsVo entity) {
        Long activeModel = entity.getActiveModel();
        Date endDate = entity.getEndDate();
        Date startDate = entity.getStartDate();
        int i = DateUtils.differentDaysByMillisecond(startDate, endDate);
        entity.setCycle(i+"");
        save(entity);
        if(activeModel != null && activeModel > 0l){
            TbFlowVo tbFlowVo = tbFlowMapper.queryById(activeModel);
            TbNodesVo nodesVo = new TbNodesVo();
            nodesVo.setProjectsId(tbFlowVo.getId());
            nodesVo.setType("flow");
            List<TbNodesVo> tbNodesVos = tbNodesService.queryAll(nodesVo);
            tbNodesVos = sortTbNodes(tbNodesVos, tbNodesVos.get(0));
            List<TbNodes> tbNodesVos_ = new ArrayList<>();
            for (TbNodesVo tbNodesVo : tbNodesVos) {
                tbNodesVo.setProjectsId(entity.getId());
                tbNodesVo.setType("project");
                tbNodesVos_.add(tbNodesVo);
            }
            tbNodesService.saveBatch(tbNodesVos_);
            TbNodes temp = tbNodesVos_.get(0);
            for (int z = 1 ; z < tbNodesVos_.size(); z++) {
                TbNodes tbNodes = tbNodesVos_.get(z);
                tbNodes.setFrom(temp.getId());
                temp.setTo(tbNodes.getId());

                tbNodesService.updateById(tbNodes);
                tbNodesService.updateById(temp);

                temp = tbNodes;
            }
        }
        return true;
    }
    @Override
    public boolean updateProject(TbProjectsVo entity) {
        Date endDate = entity.getEndDate();
        Date startDate = entity.getStartDate();
        int i = DateUtils.differentDaysByMillisecond(startDate, endDate);
        entity.setCycle(i+"");
        this.updateById(entity);
        return true;
    }
    public static List<TbNodesVo> sortTbNodes(List<TbNodesVo> edges, TbNodesVo startNode) {
        Map<Long, TbNodesVo> edgeMap = new HashMap<>();
        for (TbNodesVo edge : edges) {
            edgeMap.put(edge.getId(), edge);
        }
        List<TbNodesVo> sortedList = new ArrayList<>();
        Long currentId = startNode.getId();
        while (currentId != null) {
            TbNodesVo currentEdge = edgeMap.get(currentId);
            if (currentEdge == null) break;
            sortedList.add(currentEdge);
            if( currentEdge.getTo() == 0l){
                break;
            }
            currentId = currentEdge.getTo();
            // 检测循环或超出预期长度
            if (sortedList.size() > edges.size()) {
                throw new IllegalArgumentException("检测到循环或无效链");
            }
        }
        return sortedList;
    }
}
